{-| Module Parser contains parsec functions which use to
parse lists in haskell syntax.

Example -  Parsing a list of integers:
> parseIntList "[1,2,3,4]" ==> [1,2,3,4] 

 -}
module Parser where
import Prelude hiding (readList)
import Text.ParserCombinators.Parsec

-- |parse function for integer lists
parseIntList :: [Char] -> Either ParseError [Int]
parseIntList = readList (read::String->Int) (list (multiple digit))

-- |
readList
  :: (a -> b) 
  -> GenParser c () [a] 
  -> [c] 
  -> Either ParseError [b]
readList r p s = 
  case runParser p () [] s of
    Right xs -> Right $ map r xs
    Left e   -> Left e 

-- |parses a list of values parsed by given parser @p@
list :: GenParser Char st t -> GenParser Char st [t] 
list p = do
  { spaces
  ; char '[' ; spaces 
  ; d <- innerList p ; spaces
  ; char ']' ; spaces
  ; return d
  }

-- |parses a list without brackets
innerList :: GenParser Char st t -> GenParser Char st [t]
innerList p =
  do { spaces
     ; r <- p
     ; do 
       { char ',' 
       ; rs <- innerList p
       ; return $ r:rs
       }
       <|>
       do 
       { spaces
       ; return [r]
       }
    }
  <|>
  do { spaces 
     ; return []
     } 

-- |this parser combinator gets a parser and 
-- applies it as often as possible
multiple ::  GenParser Char st t -> GenParser Char st [t]
multiple p = do
  r <- p
  do 
  { rs <- multiple p
  ; return (r:rs)
  }
  <|> do
  { spaces
  ; return []
  }
